﻿namespace NKernel.Core
{
    using Impl;

    using Provider;

    /// <summary>
    /// Main entry point to the IKernel implementation through the use of a Builder pattern and Fluent-style
    /// programming interface
    /// </summary>
    public sealed class NKernelBuilder
    {
        #region Fields

        private IKernelProvider kernelProvider;
        private bool makeSynchronized;
        private string[] priorityComponents;

        #endregion Fields

        #region Constructors

        private NKernelBuilder()
        {
            //do nothing
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Static method for instantiating and initialising the NKernel
        /// </summary>
        /// <returns></returns>
        public static NKernelBuilder Builder()
        {
            return new NKernelBuilder();
        }

        /// <summary>
        /// If no other options are chosen, then the invocation of Build() will default to a properties-configured KernelProvider for container management.
        /// There is no specific order in which the methods should be called - the only exception is that Build() must come last in order
        /// to obtain a reference to the IKernel implementation. 
        /// </summary>
        /// <returns></returns>
        /// <example>IKernel kernel = NKernel.Builder.Build()</example>
        /// <example>IKernel kernel = NKernel.Builder.UsingWindsorProvider().Build() - this is equivalent to the basic example of NKernel.Builder().Build()</example>
        public IKernel Build()
        {
            IKernel build = kernelProvider == null ? new DefaultKernelImpl() : new DefaultKernelImpl(kernelProvider);

            if (priorityComponents != null && priorityComponents.Length > 0)
            {
                build = new PriorityKernelDecorator(build);
                build.InitPriorityList(priorityComponents);
            }

            if (makeSynchronized)
            {
                build = new SynchronizedKernelDecorator(build);
                build.InitPriorityList(priorityComponents);
            }

            return build;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="components"></param>
        /// <returns></returns>
        public NKernelBuilder GivePriority(string[] components)
        {
            priorityComponents = components;

            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public NKernelBuilder MakeSynchronized()
        {
            makeSynchronized = true;

            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public NKernelBuilder UsingWindsorProvider()
        {
            kernelProvider = new WindsorProvider();
            return this;
        }

        #endregion Methods
    }
}